/*
This file is part of IRCaBot.
IRCaBot is IRC logger with features.
Source code: https://notabug.org/acetone/ircabot.
Copyright (C) acetone, 2023.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#include "database.h"
#include "config.h"

#include <QRegularExpression>
#include <QDebug>
#include <QDir>
#include <QFile>

#define LOG_ERR qCritical().noquote() << "Db [" + m_name + "]"
#define LOG_WARN qWarning().noquote() << "Db [" + m_name + "]"
#define LOG_INFO qInfo().noquote() << "Db [" + m_name + "]"

constexpr const char DATABASES_DIR_NAME[] = "databases/";

bool Database::m_initialized = false;
std::map<QString, QMutex> Database::m_singleAccessController;

Database::Database(const QString &name) : m_name(name)
{
    bool first = m_singleAccessController.find(m_name) == m_singleAccessController.end();
    m_singleAccessController[m_name].lock();

    m_db = first ? QSqlDatabase::addDatabase("QSQLITE", m_name) : QSqlDatabase::database(m_name);
    if (first)
    {
        if (not QFile::exists(Config::workingDirectory()+DATABASES_DIR_NAME))
        {
            if (not QDir().mkdir(Config::workingDirectory()+DATABASES_DIR_NAME))
            {
                qFatal("Folder \"databases\" creating failed (maybe working directory not found or not writable)");
            }
        }
        m_db.setDatabaseName(Config::workingDirectory()+DATABASES_DIR_NAME+m_name.toLower()+".db");
    }

    if (not m_db.open())
    {
       LOG_ERR << "Connection with database failed (maybe working directory not found or not writable)";
    }
}

Database::~Database()
{
    m_db.close();
    m_singleAccessController[m_name].unlock();
}

bool Database::initialized() const
{
    return m_initialized;
}

void Database::initialize()
{
    m_initialized = true;
}

QString Database::escaped(const QString &str) const
{
    QString result {str};
    static const QRegularExpression rgx("[';`]");
    result.replace(rgx, "_");
    return result;
}
